﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Microsoft.Practices.Unity;
using TagLib;
using System.Threading;
using System.Windows;
using System.Windows.Threading;

namespace MP3Ganizer.Modules.FileView.ViewModels
{
  /// <summary>
  /// ViewModel du FileView
  /// </summary>
  public class FileViewVM: INotifyPropertyChanged, IFileViewVM 
  {
    #region Fields

    private readonly IUnityContainer _container;

    private string _artisteTitre;
    private string _artisteAlbum;
    private string _album;
    private string _titre;
    private File _file;
    private string _sourcePath;
    private string _destinationPath;
    private string _destinationDir;
    private string _sourceDir;
    #endregion
    
    #region IFileViewMainVM Members

    /// <summary> 
    /// Vue principale
    /// </summary>
    public MP3Ganizer.Modules.FileView.Views.IFileViewMainV MainView {get; private set;}

    public string ArtisteTitre
    {
        get
        {
            if(_file != null)
                return _file.Tag.FirstPerformer;
            else
                return _artisteTitre;
        }
        set
        {
            if (_file != null)
            {
                List<string> list = _file.Tag.Performers.ToList<string>();
                if (list.Count >= 1)
                    list[0] = value;
                else
                    list.Insert(0, value);
                _file.Tag.Performers = list.ToArray();
            }
            else
                _artisteTitre = value;
            OnPropertyChanged("ArtisteTitre");
            InfoFileChanged();
        }
    }

    public string ArtisteAlbum
    {
        get
        {
            if (_file != null)
                return _file.Tag.FirstAlbumArtist;
            else
                return _artisteAlbum;
        }
        set
        {
            if(_file != null)
            {
            List<string> list = _file.Tag.AlbumArtists.ToList<string>();
            if(list.Count >= 1)
                list[0] = value;
            else
                list.Insert(0, value);
            _file.Tag.AlbumArtists = list.ToArray();
            }
            else
                _artisteAlbum = value;
            OnPropertyChanged("ArtisteAlbum");
            InfoFileChanged();
        }
    }

    public string Album
    {
        get
        {
            if (_file != null)
                return _file.Tag.Album;
            else
                return _album;
        }
        set
        {
            if (_file != null)
                _file.Tag.Album = value;
            else
                _album = value;
            OnPropertyChanged("Album");
            InfoFileChanged();
        }
    }

    public string Titre
    {
        get
        {
            if (_file != null)
                return _file.Tag.Title;
            else
                return _titre;
        }
        set
        {
            if(_file != null)
                _file.Tag.Title = value;

            OnPropertyChanged("Titre");
            InfoFileChanged();
        }
    }

    public uint Piste
    {
        get
        {
            if (_file != null)
                return _file.Tag.Track;
            return 0;
        }
        set
        {
            if (_file == null)
                _file = File.Create(_sourcePath);
            _file.Tag.Track = value;
            OnPropertyChanged("Piste");
            InfoFileChanged();
        }
    }

    public string SourcePath
    {
        get
        {
                return _sourcePath.Replace(_sourceDir, "...");
        }
    }

    public string DestinationPath
    {
        get
        {
            return _destinationPath.Replace(_destinationDir, "...");
        }
        set
        {
            _destinationPath = value.Replace("...", _destinationDir);
            OnPropertyChanged("DestinationPath");
        }
    }

    public Common.Enums.DataType DataType
    {
        get;
        private set;
    }

    //private Common.Enums.StatusFichier _statusFichier = Common.Enums.StatusFichier.Undefined;
    public int Status
    {
        //get{return (int)_statusFichier;}
        get;
        private set;
    }
    #endregion

    /// <summary>
    /// Constructeur. Les paramètres sont pré-remplis par le UnityContainer.
    /// </summary>
    /// <param name="container"></param>
    /// <param name="mainView"></param>
    public FileViewVM(object obj, string destinationDir, string sourceDir)
    {
        _file = obj as File;
        
        _destinationDir = destinationDir;
        _sourceDir = sourceDir;
        if (_file == null)
        {
            _sourcePath = obj as string;
            _destinationPath = destinationDir;
            if (!System.IO.File.Exists(_sourcePath))
                return;
            System.IO.FileInfo fi = new System.IO.FileInfo(_sourcePath);
            _titre = fi.Name;
            fi.Attributes = System.IO.FileAttributes.Archive;
            if (fi.Extension.ToLower() == ".jpg" || fi.Extension.ToLower() == ".gif" || fi.Extension.ToLower() == ".bmp" || fi.Extension.ToLower() == ".png")
                DataType = Common.Enums.DataType.Image;
            else
                DataType = Common.Enums.DataType.Unknown;
        }
        else
        {
            _sourcePath = _file.Name;
            DataType = Common.Enums.DataType.Audio;
        }
        OptimizeFileView();
        InfoFileChanged();
    }

    public FileViewVM(IUnityContainer container, object obj, string destinationDir, string sourceDir):this(obj, destinationDir, sourceDir)
    {
        this._container = container;
        this._container.Resolve<Microsoft.Practices.Composite.Events.IEventAggregator>().GetEvent<MP3Ganizer.Events.User.UserActionEvent>().Subscribe(OnUserAction, Microsoft.Practices.Composite.Presentation.Events.ThreadOption.UIThread, true);
        
    }

    private void OptimizeFileView()
    {
        if (_file == null)
            return;
        if (string.IsNullOrEmpty(_file.Tag.FirstAlbumArtist) && !string.IsNullOrEmpty(_file.Tag.FirstPerformer))
            _file.Tag.AlbumArtists = new string[1] { _file.Tag.FirstPerformer };
        if (string.IsNullOrEmpty(_file.Tag.FirstPerformer) && !string.IsNullOrEmpty(_file.Tag.FirstAlbumArtist))
            _file.Tag.Performers = new string[1] { _file.Tag.FirstAlbumArtist };
        if (string.IsNullOrEmpty(_file.Tag.Title))
        {
            string filename = _file.Name.Split('\\').Last<string>();
            string extension = new System.IO.FileInfo(_file.Name).Extension;
            _file.Tag.Title = filename.Replace(extension, string.Empty);
        }
        SetStatus();
    }


    private void OnUserAction(MP3Ganizer.Events.User.UserActionEventArgs e)
    {
        if (e.Action == MP3Ganizer.Common.Enums.UserAction.SaveData)
        {
           ApplyChanges();
        }

        if (e.Action == MP3Ganizer.Common.Enums.UserAction.CopyToDestination)
        {
            ApplyAndCopyToDestination();
        }
    }

    public void ApplyChanges()
    {
        if (_file != null)
        {
            try
            {
                    _file.Save();
            }
            catch (Exception e)
            {
                ShowError(e.Message);
            }
        }
    }

    void FileAccessChanged(object sender, System.IO.FileSystemEventArgs e)
    {
        _file.Save();
    }
    public void CopyToDestination()
    {
        CopyToDestination(null);
    }
    public void CopyToDestination(IFileViewListVM list)
    {
        try
        {
            ThreadPool.QueueUserWorkItem(delegate
                    {
                        string msg = MP3Ganizer.Services.Files.FilesServices.CopyToDestination(_sourcePath, _destinationPath);
                        if(string.IsNullOrEmpty(msg))
                            Application.Current.Dispatcher.BeginInvoke(new DispatcherOperationCallback(RemoveFileFromList), DispatcherPriority.Normal, list);
                        else ShowError(msg);

                    });
        }
        catch (Exception e)
        {
            ShowError(e.Message);
        }
    }

    private object RemoveFileFromList(object file)
    {
        IFileViewListVM list = file as IFileViewListVM;
        if(list != null)
            list.RemoveFile(this);
        return null;
    }

    private void ShowError(string message)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("Une erreur est survenue lors de cette opération, veuillez résoudre le problème et réessayez.");
        sb.AppendFormat("Le problème est le suivant : {0}", message);
        MessageBox.Show(sb.ToString(), "Erreur", MessageBoxButton.OK, MessageBoxImage.Warning);
    }
    public void ApplyAndCopyToDestination()
    {
        ApplyChanges();
        CopyToDestination();

    }
    public void ShowFile()
    {
        Events.User.ShowMediaData data = new Events.User.ShowMediaData(ArtisteAlbum, Album, Titre, _sourcePath, DataType);
        this._container.Resolve<Microsoft.Practices.Composite.Events.IEventAggregator>().GetEvent<MP3Ganizer.Events.User.UserActionEvent>().Publish(new Events.User.UserActionEventArgs(Common.Enums.UserAction.ShowMedia, data));
    }
    #region INotifyPropertyChanged Members
    /// <summary>
    /// Implémentation de INotifyPropertyChanged.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
    private IUnityContainer container;
    private object x;
    private string p;

    /// <summary>
    /// Fonction de Raise de l'évènement PropertyChanged.
    /// </summary>
    /// <param name="PropertyName"></param>
    protected void OnPropertyChanged(string PropertyName)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
      }
    }

    private void InfoFileChanged()
    {
        DestinationPath = MP3Ganizer.Services.Files.FilesServices.GetDestinationPathFromSource(_file, _artisteAlbum, _album, _destinationDir, _titre);
        SetStatus();
    }

    private void SetStatus()
    {
        //if (!string.IsNullOrEmpty(Album) && !string.IsNullOrEmpty(ArtisteAlbum) && !string.IsNullOrEmpty(ArtisteTitre) && !string.IsNullOrEmpty(Titre) && Piste != 0)
        //    _statusFichier = Common.Enums.StatusFichier.Complet;
        //else if (string.IsNullOrEmpty(Titre))
        //    _statusFichier = Common.Enums.StatusFichier.SansTitre;
        //else if (string.IsNullOrEmpty(ArtisteAlbum))
        //    _statusFichier = Common.Enums.StatusFichier.SansArtisteAlbum;
        //else if (string.IsNullOrEmpty(Album))
        //    _statusFichier = Common.Enums.StatusFichier.SansAlbum;
        //else if (string.IsNullOrEmpty(ArtisteTitre))
        //    _statusFichier = Common.Enums.StatusFichier.SansArtisteTitre;
        //else if (Piste == 0)
        //    _statusFichier = Common.Enums.StatusFichier.SansNumero;
        int status = 0;
        if (!string.IsNullOrEmpty(Titre))
            status += 30;
        if (!string.IsNullOrEmpty(ArtisteAlbum))
            status += 25;
        if (!string.IsNullOrEmpty(ArtisteTitre))
            status += 20;
        if (!string.IsNullOrEmpty(Album))
            status += 15;
        if (Piste != 0)
            status += 10;
        Status = status;
        OnPropertyChanged("Status");
    }
    #endregion


    public bool IsSourceFileExists()
    {
        bool exists = System.IO.File.Exists(_sourcePath);
        return exists;
    }
  }
}
